import mimetypes
from datetime import datetime

from django.shortcuts import get_object_or_404, render_to_response
from django.http import HttpResponseRedirect, Http404, HttpResponse, HttpResponseNotFound
from django.template import RequestContext
from django.db.models import Q

from django.views.decorators.http import condition


from assets.urls import default_path
from damn import TranscoderInstance

from assets.models import Asset, Format, Version

from assets.util import HttpResponseSerialized, get_services

from assets.search import searchAssets

from files.models import File
     
def services(request):
  """
  List all the services
  and help and arguments
  """
  services = get_services()
  services = [s for s in services if not 'django.views.static.serve' == s.module]
  return render_to_response('services.html', {'services': services}, context_instance=RequestContext(request))


def index(request):	
  return render_to_response('index.html', {}, context_instance=RequestContext(request))
  
def user(request):	
  return render_to_response('registration/user.html', {}, context_instance=RequestContext(request))


def transcode(request, as_id):
  """
  Purpose: Transcode a given asset to the specified format.
  """
  asset = get_object_or_404(Asset, id=as_id)
  assetRef = Asset.objects.get_reference(id=as_id)
  format = request.GET.get('format', 'image/jpeg')
  
  trans = TranscoderInstance()
  
  args = {}
  noCache = False
  for k,v in request.GET.items():
    if k == 'noCache':
      noCache = True
    elif not k == 'format':
      args[str(k)] = v
  
  f, c = Format.objects.get_or_create(name=format)
  if c: f.save()
  version, created = Version.objects.get_or_create(asset=asset, 
                                                  format=f, 
                                                  arguments=str(args), 
                                                  defaults={'version':1})
  if created: version.save() 
  
  eTag = 'W/"'+str(version.version)+'"'
  if 'HTTP_IF_NONE_MATCH' in request.META:
	if request.META['HTTP_IF_NONE_MATCH'] == eTag:
		return HttpResponse(status=304)
  
  if noCache:
    path = trans.transcode(assetRef, format, **args) 
  else:  
    path, created = trans.get_or_transcode(assetRef, format, **args)   
  
  if request.GET.get('location', False):
    return HttpResponse(str(path.split(default_path())[1]))
    
  try:
    f = open(path, 'rb')
    data = f.read()
    f.close()
    response = HttpResponse(data, mimetype=mimetypes.guess_type(path, False)[0])
    response['Content-Length'] = str(len(data))
    response['Access-Control-Allow-Origin'] = '*'
    response['eTag'] = eTag
    if 'download' in request.GET:
      response['Content-Disposition'] = 'attachment; filename='+os.path.basename(path)
    return response
  except IOError:
    return HttpResponseNotFound("IOError for %s"%(path))


def destination_formats(request, as_id):  
  asset = get_object_or_404(Asset.objects, id=as_id)
  
  trans = TranscoderInstance()
  
  formats = trans.formats_clean(asset.format.name)

  return HttpResponseSerialized(request, formats)


def latest_files_date(request):
  if request.method == 'GET':
    fileId = request.GET.get('fileid', None)
    try:
      if fileId == "-1":
        f = File.objects.exclude(repository=None).filter(parent=None).latest('stamp').stamp
        r = Repository.objects.latest('stamp').stamp
        return f if f > r else r # return latest of the latests.
      elif fileId != "0":
        file = File.objects.get(id=int(fileId))
        return file.children.latest('stamp').stamp
    except Asset.DoesNotExist:
      pass
        
@condition(last_modified_func=latest_files_date)
def files(request):	
  def SerializeRep(repository, json):
    d = { "data" : repository.name, "state" : "open" , "attr" : { "rel": "root",}, "children" : []}
    for child in repository.children:
      SerializeFile(child, d['children'])
    json.append(d)
    
  def SerializeFile(file, json):
    if file.parent:
      d = {'data': file.fileName, 'attr' : { 'rel': 'file' , 'fileid': file.id, },}
      format = mimetypes.guess_type(file.fileName, False)[0]
      if file.directory and file.children.count() > 0:
        d["attr"]["rel"] = 'folder'
        d["children"] = []
        d["state"] = "closed"
      elif format == 'application/blender':
        d["attr"]["rel"] = 'blend'
      elif format and format.startswith('image/'):
        d["attr"]["rel"] = 'image'
      json.append(d)
    else:#Collapse root file
      for child in file.children:
        SerializeFile(child, json)    
   
  data = []
  
  if request.method == 'GET':
    fileId = request.GET.get('fileid', None)    
    if fileId == "-1":
      for rep in Repository.objects.all():
        SerializeRep(rep, data)
    elif fileId != "0":
      file = File.objects.get(id=int(fileId))
      for child in file.children:
        SerializeFile(child, data)
  
  return HttpResponseSerialized(request, data)


def GetChildren(file, data):
  if not file.directory:
    data.append(int(file.id))
  for child in file.children:
    GetChildren(child, data)

def latest_file_children_assets_date(request, file_id):
  files = []
  GetChildren(get_object_or_404(File, id=file_id), files)
  if len(files) > 0:
    try:
      return Asset.objects.filter(files__in=files).latest('stamp').stamp
    except Asset.DoesNotExist:
      pass
  return None
        
@condition(last_modified_func=latest_file_children_assets_date)
def file_children_assets(request, file_id):
  files = []
  GetChildren(get_object_or_404(File, id=file_id), files)
  
  start = request.GET.get('start', 0)
  end = request.GET.get('end', None)
  
  start = 0 if start == 'NaN' else start
  end = 0 if end == 'NaN' else end
  
  if len(files) > 0:
    assets = Asset.objects.filter(files__in=files) 
    count = assets.count()
    assets = assets[start:end]
  else:
    assets = Asset.objects.none()
    count = assets.count()

  response = HttpResponseSerialized(request, assets, fields=('subName', 'format'))
  response["Assets-Total-Count"] = count
  return response


def parents(request, as_id):
  asset = get_object_or_404(Asset, id=as_id)
  
  parents = []
  
  parent = asset.file
  while parent: 
    if not parent.parent: break#Collapsed root file
    parents.append(parent)
    parent = parent.parent
  
  parents.reverse()
  
  return HttpResponseSerialized(request, parents, fields=('id',))


def dependencies(request, as_id):  
  """
  Purpose: Discover dependencies for the supplied asset, other assets which this one requires to function properly. 
  
  <a href="http://wiki.peragro.org/index.php/Tools/DAMN/API#assets.2F.5Bassetid.5D.2Fdependencies.3Fformat.3D.28json.7Cxml.29">http://wiki.peragro.org/index.php/Tools/DAMN/API#assets.2F.5Bassetid.5D.2Fdependencies.3Fformat.3D.28json.7Cxml.29</a>
  """ 
  asset = get_object_or_404(Asset, id=as_id)
  return HttpResponseSerialized(request, asset.dependencies.all(), fields=('subName', 'format'))
  
   
def metadata(request, as_id):
  """
  Purpose: Read the metadata of an asset. 
  
  <a href="http://wiki.peragro.org/index.php/Tools/DAMN/API#assets.2F.5Bassetid.5D.2Fmetadata.3Fformat.3D.28json.7Cxml.29">http://wiki.peragro.org/index.php/Tools/DAMN/API#assets.2F.5Bassetid.5D.2Fmetadata.3Fformat.3D.28json.7Cxml.29</a>
  """  
  asset = get_object_or_404(Asset, id=as_id)
  return HttpResponseSerialized(request, asset.metadata_set.all(), fields=('name', 'value'))


def info(request, as_id):  
  asset = get_object_or_404(Asset, id=as_id)
  return HttpResponseSerialized(request, asset, fields=('files', 'subName', 'format'))


def anvil(request, as_id):  
  asset = get_object_or_404(Asset, id=as_id)
  
  data = {'subName': asset.subName,
          'format__name': asset.format.name}
  
  deps = asset.dependencies.values('id', 'subName', 'format__name')
  data['dependencies'] = list(deps)
  
  versions = asset.version_set.values('format__name', 'version', 'arguments')
  data['versions'] = list(versions)
  
  return HttpResponseSerialized(request, data)  
  

def allformats(request):   
  data = list(Format.objects.values('id', 'name', 'type__name').distinct())
  return HttpResponseSerialized(request, data)


def search(request):  
  """
  Purpose: Find assets. All arguments are optional, calling without arguments returns the full asset list. 
  
  <a href="http://wiki.peragro.org/index.php/Tools/DAMN/API#assets.2Fsearch.3Fformat.3D.28json.7Cxml.29">http://wiki.peragro.org/index.php/Tools/DAMN/API#assets.2Fsearch.3Fformat.3D.28json.7Cxml.29</a>
  """
  if request.method == 'GET':
    assets, total = searchAssets(request)
    
    if request.GET.get('everything', False):
      fields = None 
      assets = list(assets)
      assets += list(MetaData.objects.filter(asset__in=assets).distinct()) + list(Collection.objects.filter(assets__in=assets).distinct())
    else:
      fields = ('subName', 'format')
    
    response = HttpResponseSerialized(request, assets, fields=fields)
    response["Assets-Total-Count"] = total
    return response
    
  return HttpResponseNotFound('Search needs to be a GET request!')
 
  
def image_similar(request, as_id):  
  asset = get_object_or_404(Asset, id=as_id)
  def Quote(s):
    return '\''+s+'\''

  prx = 'avg-color-count-'
  red = asset.metadata_set.get(name=prx+'red').value
  green = asset.metadata_set.get(name=prx+'green').value
  blue = asset.metadata_set.get(name=prx+'blue').value
  
  meta = MetaData.objects.exclude(asset=asset.id)
  
  epsilon = request.GET.get('epsilon', 15)
  
  data = meta.filter(name=prx+'red').extra(where=['abs(CAST(value as INTEGER) - '+red+') < '+str(epsilon)])
  data = meta.filter(asset__in=data.values('asset'), name=prx+'green').extra(where=['abs(CAST(value as INTEGER) - '+green+') < '+str(epsilon)])
  data = meta.filter(asset__in=data.values('asset'), name=prx+'blue').extra(where=['abs(CAST(value as INTEGER) - '+blue+') < '+str(epsilon)])
  
  data = data.values('asset').distinct()
  
  response = HttpResponse() 
  response.write('<html>')
  response.write('<body>')
  response.write('<img title="'+str(asset.id)+'" src="/assets/'+str(asset.id)+'/transcode/?format=image/png&sizex=128&sizey=128"></img><br /><br />')
  for d in data:
    id = str(d['asset'])
    response.write('<img title="'+id+'" src="/assets/'+id+'/transcode/?format=image/png&sizex=128&sizey=128"></img>')
  response.write('</body>')
  response.write('</html>')
  
  return response


def transcoders_formats(request):  
  """
  Purpose: Dynamic discovery of static file paths in JavaScript. 
  
  <a href="http://wiki.peragro.org/index.php/Tools/DAMN/API#transcoders.2Fformats.3Fformat.3D.28json.7Cxml.29">http://wiki.peragro.org/index.php/Tools/DAMN/API#transcoders.2Fformats.3Fformat.3D.28json.7Cxml.29</a>
  """
  trans = TranscoderInstance()
  
  formats = trans.templates()
  
  for src, dsts in formats.items():
    for dst, d in dsts.items():
      newoptions = []
      for o in d['options']:
        newoptions.append( {'name': str(o[0]), 'type': str(getattr(o[1], '__name__', 'unknown type')), 'default': str(o[2]),} )
      d['options'] = newoptions
    
  return HttpResponseSerialized(request, formats)   
  
  
  
